Thread: How do I run cmd.exe as Administrator[C/Win32/CreateProcessAsUser()]

  1. #1
    Registered User HelpfulPerson's Avatar
    Join Date
    Jun 2013
    Location
    Over the rainbow
    Posts
    288

    How do I run cmd.exe as Administrator[C/Win32/CreateProcessAsUser()]

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    #define WIN_32_LEAN_AND_MEAN
    #include <windows.h>
    
    
    /* Credit to : http://msdn.microsoft.com/en-us/library/windows/desktop/ms680582(v=vs.85).aspx */
    
    
    void ErrorExit(LPTSTR lpszFunction)
    {
        // Retrieve the system error message for the last-error code
    
    
        LPVOID lpMsgBuf;
        LPVOID lpDisplayBuf;
        DWORD dw = GetLastError();
    
    
        FormatMessage
        (
            FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            dw,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR) &lpMsgBuf,
            0,
            NULL
        );
    
    
        // Display the error message and exit the process
    
    
        lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
        sprintf(lpDisplayBuf, "%s failed with error %d: %s", lpszFunction, (int)dw, (char *)lpMsgBuf);
        MessageBox(NULL, lpDisplayBuf, "Error", MB_OK);
    
    
        LocalFree(lpMsgBuf);
        LocalFree(lpDisplayBuf);
        ExitProcess(dw);
    }
    
    
    char * s_strdup( char * dest, char * string )
    {
        char * temp = NULL;
    
    
        if ((temp = strrchr(string, '\n')))
            *temp = '\0';
    
    
        dest = malloc(strlen(string) + 1);
    
    
        if ( !dest )
        {
            perror("Malloc");
            exit(1);
        }
    
    
        return strcpy(dest, string);
    }
    
    
    int main( )
    {
        LPSTR username = NULL;
        LPSTR password = NULL;
        HANDLE hadmin_token;
        HANDLE new_hadmin_token;
        PHANDLE new_admin_token = &new_hadmin_token;
        PHANDLE admin_token = &hadmin_token;
        PROCESS_INFORMATION cmd_info;
        LPPROCESS_INFORMATION pcmd_info = &cmd_info;
        char buffer[BUFSIZ] = {0};
    
    
        printf("Enter username to impersonate : ");
        fgets(buffer, BUFSIZ, stdin);
        username = s_strdup(username, buffer);
        memset(buffer, 0, BUFSIZ);
        printf("Enter %s's password : ", username);
        fgets(buffer, BUFSIZ, stdin);
        password = s_strdup(password, buffer);
        memset(buffer, 0, BUFSIZ);
    
    
        if ( !LogonUser(username, "", password, LOGON32_LOGON_NETWORK | LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, admin_token) )
            ErrorExit("LogonUser");
    
    
        if ( !ImpersonateLoggedOnUser( hadmin_token ) )
            ErrorExit("ImpersonateLoggedOnUser");
    
    
        DuplicateTokenEx(hadmin_token, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, new_admin_token );
    
    
        if ( !CreateProcessAsUser(new_hadmin_token, "C:\\Windows\\System32\\cmd.exe", NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, "C:\\Windows\\System32\\cmd.exe", NULL, pcmd_info ))
            ErrorExit("CreateProcessAsUser");
    
    
        if ( !RevertToSelf() )
            ErrorExit("RevertToSelf");
    
    
        CloseHandle(hadmin_token);
        CloseHandle(new_hadmin_token);
    
    
        return 0;
    }
    I'm an administrator on my home computer, so in a way I don't need this. I was wondering though if I ever wanted to do this as a standard user, if I could somehow do that with CreateProcessAsUser(). I have the impersonation code right I think, but the function parameters for creating the process are way off.

    The current error message I get is from that function with " Could not load at address 0x00000000" or something like that.
    "Some people think they can outsmart me, maybe. Maybe. I've yet to meet one that can outsmart bullet" - Meet the Heavy, Team Fortress 2

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,662
    Well the first thing to check is whether you're compiling in ANSI or UNICODE mode.

    If you're compiling in UNICODE mode (which became the default for visual studio some years ago), then all your ANSI API calls are just going to generate garbage strings when passed to UNICODE functions.

    Are you getting any warnings when you compile this, or did you just throw in a load of casts to make the compiler STFU?

    Read this, and made use of the correct mapping functions and data types to insulate you from differences between ANSI and UNICODE
    Generic-Text Mappings
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Mar 2010
    Posts
    583
    You can't do this with CreateProcess. Here's a nice blog post:
    Why Can

    Couple of things wrong with your CreateProcessAsUser call (in case you want to keep this code for something else):
    lpCurrentDirectory is optional, can be NULL. But if it's not NULL, it needs to point to a directory, not a file.
    lpStartupInfo is not optional, can't be NULL. You can create a STARTUPINFO struct and memset it to all 0s, and pass the address of that. You should memset the PROCESS_INFORMATION struct to zeros, too.

    There's a couple of bits on MSDN about how app developers should avoid needing to run as administrator:
    Windows Vista Application Development Requirements for User Account Control (UAC)
    Running with Administrator Privileges (Windows)

    Apparently you use "runas" with ShellExecute() to start a process with elevated privileges. Code example here:
    Elevate through ShellExecute - Vista Compatibility Team Blog - Site Home - MSDN Blogs

    If you're on a Windows which pops up UAC prompts, it'll pop up a UAC prompt at this point.

    You should identify what specific elevated privileges you need, and check to see if the user already has them. Here's some stuff about that Privileges (Windows)

    Seems the gist of all this is that admin access shouldn't be used as a blunt instrument to bypass security settings -- if you can gain access to things in more 'legitimate' ways then you should.

  4. #4
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Your s_strdup function is a little wacky. It should be:
    Code:
    char *s_strdup(char *str)
    {
        char *s = malloc(strlen(str) + 1);
     
        if (!s)
        {
            perror("s_strdup");
            exit(1);
        }
     
        return strcpy(s, str);
    }
    The code that replaces a newline with the nul shouldn't be in the s_strdup function. Add it to an fgets wrapper function instead.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  5. #5
    Registered User ledow's Avatar
    Join Date
    Dec 2011
    Posts
    435
    And just from an IT/Network manager's point of view - if your program needs to do this, you're doing something wrong anyway. Seriously. Either tell people "You are not an administrator, but you need to be to continue" when the program is run, or tell people that the program ONLY works if run as Administrator.

    Because, almost certainly, whatever you are doing, it's something that the Administrator needs to be present for, know about, supply his password, and he's not going to type it into a random app unless it obviously NEEDS it, and then Windows will quite happily let him "Run As Administrator" from the context menu for the executable anyway.

    Whenever you find yourself thinking "Oh, I just need to wipe out these permissions, or change this security setting, or run as Administrator", think again. Unless it's something so blindingly obvious that it needs administrator access, most users will NOT want to do it. And if they do need to, they will do it while logged on as Administrator, not let some random program loose with their admin password and let it elevate itself.

    To be honest, the number of times I've used even "runas" is very minimal, and almost always to LOWER privileges to test things for my users rather than the other way around, and there is always a better way to do it by just logging in as someone who has the required privileges (or not) and running the program direct.

    As soon as you feel the need to elevate privileges, stop and think. And if you try to sneakily elevate privileges, your program will go in the bin. Home use or not, it's a bad habit to get into and we've JUST started weaning Windows people off "everyone is an admin" operating systems to the point where running as administrator is almost non-existent now and only required for things like device drivers.

    - Compiler warnings are like "Bridge Out Ahead" warnings. DON'T just ignore them.
    - A compiler error is something SO stupid that the compiler genuinely can't carry on with its job. A compiler warning is the compiler saying "Well, that's bloody stupid but if you WANT to ignore me..." and carrying on.
    - The best debugging tool in the world is a bunch of printf()'s for everything important around the bits you think might be wrong.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Sorry. The administrator has banned your IP address
    By Brain Cell in forum A Brief History of Cprogramming.com
    Replies: 12
    Last Post: 05-14-2005, 02:36 PM
  2. What's a job as a systems administrator like?
    By Terrance in forum A Brief History of Cprogramming.com
    Replies: 3
    Last Post: 05-09-2004, 08:37 AM
  3. If you were the administrator of this website!
    By ammar in forum A Brief History of Cprogramming.com
    Replies: 40
    Last Post: 07-20-2003, 04:55 PM
  4. Another Administrator.
    By Sentaku senshi in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 08-14-2002, 06:53 PM
  5. Gain Administrator Right on NT4
    By Unregistered in forum Windows Programming
    Replies: 1
    Last Post: 01-09-2002, 12:31 PM